import com.google.common.collect.Lists;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

class FibonacciSupplier implements Supplier<Long> {

    long a = 0;

    long b = 1;

    @Override
    public Long get() {
        long x = a + b;
        a = b;
        b = x;
        return a;
    }
}

public class FibonacciStream {

    public static void main(String[] args) {
//        Stream<Long> fibonacci = Stream.generate(new FibonacciSupplier());
//        fibonacci.limit(10).forEach(System.out::println);
//        Stream<Double> piStream = Stream.generate(new PiSupplier());
//        piStream.skip(100).limit(10)
//                .forEach(System.out::println);
//        Stream<Double> piStream2 = Stream.generate(new PiSupplier());
//        piStream2.map(new EulerTransform())
//                .limit(10)
//                .forEach(System.out::println);
        List<Integer> nums = Lists.newArrayList(1,1,null,2,3,4,null,5,6,7,8,9,10);
       List<Integer> numsWithoutNull = nums.stream().filter(num -> num != null).
               collect(ArrayList::new,
                       (list, item) -> list.add(item),
                       (list1, list2) -> list1.addAll(list2));
    }
}

class PiSupplier implements Supplier<Double> {

    double sum = 0.0;

    double current = 1.0;

    boolean sign = true;

    @Override
    public Double get() {
        sum += (sign ? 4 : -4) / this.current;
        this.current = this.current + 2.0;
        this.sign = !this.sign;
        return sum;
    }
}

class EulerTransform implements Function<Double, Double> {

    double n1 = 0.0;

    double n2 = 0.0;

    double n3 = 0.0;

    @Override
    public Double apply(Double t) {
        n1 = n2;
        n2 = n3;
        n3 = t;
        if (n1 == 0.0) {
            return 0.0;
        }
        return calc();
    }

    double calc() {
        double d = n3 - n2;
        return n3 - d * d / (n1 - 2 * n2 + n3);
    }
}
